<template>
  <div class="typing-game-conatiner">
    <audio
      controls="true"
      autoplay="true"
      name="media"
      loop="true"
      hidden="true"
    >
      <source src="~@/assets/audio/玩玩小游戏.mp3" type="audio/mpeg" />
    </audio>
    <img
      src="~@/assets/img/typing_game/pause.png"
      @click="stop"
      class="pause_left pointer"
      alt=""
    />
    <!-- 随机字母方块 -->
    <div class="game_content">
      <span
        v-for="(item, index) in letterList"
        :key="item.id"
        :ref="`letter${item.id}`"
        :style="{
          top: item.top/192 + 'rem',
          left: item.left/192 + 'rem',
        }"
        class="block"
        :class="{ active: index == currentIndex }"
      >
        <span v-for="(letter, index1) in item.letter" :key="index1">{{
          letter
        }}</span>
      </span>
      <ul class="rocket_group" ref="rocket_group">
        <li class="rocket_item" v-for="item of 9" :key="item">
          <img
            :ref="`rocket${item}`"
            class="rocket_s"
            v-if="item != 5"
            src="~@/assets/img/typing_game/rocket_s.png"
            alt=""
          />
          <img
            class="rocket_b"
            v-else
            src="~@/assets/img/typing_game/rocket_b.png"
            alt=""
          />
        </li>
      </ul>
    </div>
    <!-- 暂停弹框 -->
    <div class="mosk" v-if="isPause">
      <div class="box">
        <img
          class="title"
          src="~@/assets/img/typing_game/pause_title.png"
          alt=""
        />
        <div class="content">
          <img
            @click="goGameCenter"
            class="first pointer"
            src="~@/assets/img/typing_game/go_center.png"
            alt=""
          />
          <img
            @click="continu"
            class="secend pointer"
            src="~@/assets/img/typing_game/start.png"
            alt=""
          />
        </div>
      </div>
    </div>
    <!-- 失败与成功弹框 -->
    <div class="mosk" v-if="isFail">
      <div
        class="fail_box"
        :style="{
          background: `url(${picture()})`,
          'background-size': `100% 100%`,
        }"
      >
        <div class="content">
          <span class="icon"></span>
          <div>
            <span class="title">学币{{ fruitCoinNum }}</span>
            <div class="progress">
              <el-progress
                :text-inside="true"
                :stroke-width="16"
                :percentage="progressNum"
                status="warning"
              ></el-progress>
            </div>
          </div>
        </div>
        <div class="footer">
          <div class="btn_group">
            <img
              @click="goGameCenter"
              class="first pointer"
              src="~@/assets/img/typing_game/go_center_01.png"
              alt=""
            />
            <img
              @click="start"
              class="secend pointer"
              src="~@/assets/img/typing_game/agin.png"
              alt=""
            />
            <img
              v-if="this.progressNum >= 75"
              @click="next"
              class="third pointer"
              src="~@/assets/img/typing_game/next_01.png"
              alt=""
            />
          </div>
        </div>
      </div>
    </div>
    <waningDialog
      :text="text"
      :dialog="dialogFlag"
      @closeEvent="closeEvent"
      @confirmEvent="confirmEvent"
    ></waningDialog>
  </div>
</template>
<script>
import waningDialog from "../commponents/waning-dialog.vue";
import { addChallengeRecord } from "@/api/game.js";
// const defaultWord = ["F", "J"];
const keyGroup = {
  2: ["F", "J"],
  4: ["D", "K"],
  5: ["F", "J", "D", "K"],
  7: ["S", "Y", "M"],
  8: ["E", "G", "U"],
  9: ["S", "Y", "M", "E", "G", "U"],
  10: ["S", "Y", "M", "E", "G", "U"],
  12: ["A", "Z", "P", "C"],
  13: ["Q", "L", "D", "N"],
  14: ["A", "Z", "P", "C", "Q", "L", "D", "N"],
  15: ["A", "Z", "P", "C", "Q", "L", "D", "N"],
  17: ["X", "O"],
  18: ["T", "I", "B"],
  19: [
    "A",
    "B",
    "C",
    "D",
    "E",
    "F",
    "G",
    "H",
    "I",
    "J",
    "K",
    "L",
    "M",
    "N",
    "O",
    "P",
    "Q",
    "R",
    "S",
    "T",
    "U",
    "V",
    "W",
    "X",
    "Y",
    "Z",
  ],
  20: [
    "A",
    "B",
    "C",
    "D",
    "E",
    "F",
    "G",
    "H",
    "I",
    "J",
    "K",
    "L",
    "M",
    "N",
    "O",
    "P",
    "Q",
    "R",
    "S",
    "T",
    "U",
    "V",
    "W",
    "X",
    "Y",
    "Z",
  ],
};
const _TARGET_CONFIG = {
  speed: 1.3,
  max_length: 6,
};
// 总生成单词数
const max_num = 20;
const defailtConfig = {
  requestId: 0,
  // animationStartTime: 0,
  element: null,
  state: "stopped",
  stoppedAt: 0,
};
const menu = {
  "65": 0,
  "194": 1,
  "325": 2,
  "455": 3,
  "827": 4,
  "957": 5,
  "1087": 6,
  "1217": 7,
};
const indexArr = [0, 1, 2, 3, 4, 5, 6, 7];
const videoArr = [1, 3, 6, 11, 16];
export default {
  components: {
    waningDialog,
  },
  data() {
    return {
      active: null,
      speed: 0.1,
      max_num: 10,
      text: "再次闯关需要扣除1个学币",
      dialogFlag: false,
      smashNumber: 0,
      totalNumber: 0,
      distance: 0,
      rectTop: 0,
      defaultWord: [],
      isFail: false,
      initLeft: [65, 194, 325, 455, 827, 957, 1087, 1217], // 641
      defaultConfig: Object.assign({}, _TARGET_CONFIG),
      isPause: false,
      state: "stopped",
      letterList: [],
      currentIndex: 0,
      requestId: null,
      rocketGroup: [],
      timer: null,
      fruitCoinNum: 0,
      progressNum: 0,
      answer: "",
      type: null,
    };
  },
  watch: {
    distance(nv) {
      if (nv <= -68) {
        let data = {
          type: this.$route.query.type,
        };
        this.progressNum = Math.floor((this.smashNumber / this.max_num) * 100);
        if (this.progressNum > 75) {
          data.pass = 1;
        } else {
          data.pass = 0;
        }
        data.score = this.progressNum;
        this.addChallengeRecord(data);
        this.stop("end");
      }
    },
    smashNumber(nv) {
      if (nv >= this.max_num) {
        this.progressNum = 100;
        this.addChallengeRecord({
          type: this.$route.query.type,
          score: 100,
          pass: 1,
        });
        this.stop("end");
      }
    },
    "$route.query.type"() {
      this.defaultWord = keyGroup[this.$route.query.type];
      this.type = this.$route.query.type;
      // this.currentIndex=0
      this.setMaxNumber();
      this.start();
    },
  },
  methods: {
    confirmEvent() {
      // this.$router.push({
      //   name: "typingGameCenterPractice",
      //   query: {
      //     type: this.currentType,
      //   },
      // });
      if (this.text == "即将前往主页进入视频学习") {
        this.goGameCenter();
      }
      this.dialogFlag = false;
    },
    closeEvent() {
      this.dialogFlag = false;
    },
    async addChallengeRecord(data) {
      const res = await addChallengeRecord(data);
      if (res.data.integral) {
        this.fruitCoinNum =
          Number(res.data.integral) >= 0
            ? `+${res.data.integral}`
            : res.data.integral;
      } else {
        this.fruitCoinNum = 0;
      }
    },
    next() {
      let type = Number(this.$route.query.type) + 1;
      if (videoArr.includes(type)) {
        this.dialogFlag = true;
        this.text = "即将前往主页进入视频学习";
        return;
      }
      this.$router.push({
        name: "typingGameCenterPractice",
        query: {
          type,
        },
      });
    },
    handleKeyPress(key) {
      let flag = this.rocketGroup.find((item) => {
        console.log(item.index, "item.index");
        console.log(
          this.letterList[this.currentIndex].index,
          "this.letterList[this.currentIndex].index"
        );
        return item.index == this.letterList[this.currentIndex].index;
      });
      if (flag != undefined) return;
      let tag = true;
      this.answer += key;
      this.answer.split("").forEach((item, index) => {
        if (!tag) return;
        if (item == this.letterList[this.currentIndex].letter[index]) {
          this.letterList[this.currentIndex].element[0].children[
            index
          ].classList.add("success_color");
        } else {
          this.letterList[this.currentIndex].element[0].children[
            index
          ].classList.add("danger_color");
          tag = false;
        }
      });
      if (
        this.answer.length != this.letterList[this.currentIndex].letter.length
      )
        return;
      if (key == this.letterList[this.currentIndex].letter || tag) {
        this.answer = "";
        let initIndex = this.letterList[this.currentIndex].index;
        let index = this.letterList[this.currentIndex].index;
        if (this.letterList[this.currentIndex].index > 3) {
          index += 2;
        } else {
          index += 1;
        }
        this.rocketGroup.push({
          index: initIndex,
          element: this.$refs[`rocket${index}`],
          animationStartTime: window.performance.now(),
        });
        this.currentIndex += 1;
      }
    },
    // 生成字母长度
    randomWordNumber(count) {
      let str = "";
      while (count > 0) {
        str += this.defaultWord[
          Math.floor(Math.random() * this.defaultWord.length)
        ];
        count -= 1;
      }
      return str;
    },
    // 生成随机字母
    randomNumber(that) {
      let defaultLetterConfig = {
        letter: "",
        left: 0,
        top: -75,
      };
      if (this.totalNumber < 10) {
        defaultLetterConfig.letter = this.randomWordNumber(1);
      } else if (this.totalNumber < 20) {
        defaultLetterConfig.letter = this.randomWordNumber(2);
      } else if (this.totalNumber < 30) {
        defaultLetterConfig.letter = this.randomWordNumber(3);
      } else {
        defaultLetterConfig.letter = this.randomWordNumber(4);
      }
      let index;
      let arr = [...indexArr];
      if (that.letterList && that.letterList[that.letterList.length - 1]) {
        arr = arr.filter(
          (item) => item != that.letterList[that.letterList.length - 1].index
        );
      }
      index = arr[Math.floor(Math.random() * arr.length)];
      defaultLetterConfig.left = this.initLeft[index];
      defaultLetterConfig.index = index;
      return defaultLetterConfig;
    },
    gostudyIndex() {
      this.$router.push({
        name: "studyIndex",
      });
    },
    goGameCenter() {
      this.$router.push({
        name: "typingGameCenter",
        query: {
          active: this.active,
        },
      });
    },
    picture() {
      if (this.progressNum < 30) {
        return require("../../../../assets/img/typing_game/fail-00.png");
      } else if (this.progressNum < 75) {
        return require("../../../../assets/img/typing_game/fail-01.png");
      } else if (this.progressNum < 90) {
        return require("../../../../assets/img/typing_game/succeed-02.png");
      } else {
        return require("../../../../assets/img/typing_game/succeed-03.png");
      }
    },
    async start() {
      this.clearCurrentClass();
      this.rocketGroup = [];
      this.currentIndex = 0;
      this.isPause = false;
      this.isFail = false;
      (this.smashNumber = 0), (this.totalNumber = 0), (this.letterList = []);
      this.initLetter();
      await this.$nextTick();
      console.log("test");
      this.letterList[0].element = this.$refs[`letter1`];
      console.log(222222);
      this.state = "move";
      if (this.requestId) {
        window.cancelAnimationFrame(this.requestId);
      }
      this.letterList[0].animationStartTime = window.performance.now();
      this.requestId = window.requestAnimationFrame(this.animateWrapper);
      this.timer = setInterval(() => {
        this.initLetter();
      }, 1000);
    },
    async animateWrapper(timestamp) {
      this.animate(timestamp);
      if (this.isPause == false) {
        this.requestId = window.requestAnimationFrame(this.animateWrapper);
      }
    },
    animate(timestamp) {
      this.rocketGroup.forEach((item, index) => {
        const count = timestamp - this.rocketGroup[index].animationStartTime;
        if (this.rocketGroup[index].element) {
          this.rocketGroup[
            index
          ].element[0].style.transform = `translateY(${-0.5 * count}px)`;
        }
      });
      this.letterList.forEach((item, index) => {
        const count = timestamp - this.letterList[index].animationStartTime;
        if (this.letterList[index].element) {
          this.letterList[
            index
          ].element[0].style.transform = `translate(-50%,${this.speed *
            count}px)`;
        }
      });
      let rect2 = null;
      if (this.letterList.length) {
        rect2 = this.letterList[0].element[0].getBoundingClientRect();
        if (this.rectTop - rect2.top <= -68) {
          this.distance = this.rectTop - rect2.top;
        }
      }
      if (this.rocketGroup.length) {
        const rect1 = this.rocketGroup[0].element[0].getBoundingClientRect();
        if (
          rect1.left < rect2.right &&
          rect1.right > rect2.left &&
          rect1.top < rect2.bottom &&
          rect1.bottom > rect2.top
        ) {
          this.rocketGroup[0].element[0].style.transform = `translateY(0)`;
          this.currentIndex -= 1;
          this.rocketGroup.shift();
          this.letterList.shift();
          this.smashNumber += 1;
        }
      }
    },
    stop(tag) {
      clearInterval(this.timer);
      if (tag == "end") {
        this.isFail = true;
      } else {
        this.isPause = true;
      }
      if (this.state === "stopped") return;
      this.rocketGroup.forEach((item, index) => {
        this.rocketGroup[index].stoppedAt = window.performance.now();
      });
      this.letterList.forEach((item, index) => {
        this.letterList[index].stoppedAt = window.performance.now();
      });
      if (this.requestId) {
        window.cancelAnimationFrame(this.requestId);
        this.requestId = null;
      }
      this.state = "stopped";
    },
    continu() {
      this.timer = setInterval(() => {
        this.initLetter();
      }, 1000);
      this.isPause = false;
      if (this.state === "move") return;
      this.rocketGroup.forEach((item, index) => {
        this.rocketGroup[index].animationStartTime +=
          window.performance.now() - this.rocketGroup[index].stoppedAt;
      });
      this.letterList.forEach((item, index) => {
        this.letterList[index].animationStartTime +=
          window.performance.now() - this.letterList[index].stoppedAt;
      });
      this.requestId = window.requestAnimationFrame(this.animateWrapper);
      this.state = "move";
    },
    async initLetter() {
      if (this.totalNumber >= this.max_num) {
        return;
      }
      let initLetter = {};
      let that = this;
      initLetter = this.randomNumber(that);
      if (this.letterList.length == 0) {
        initLetter.id = 1;
      } else {
        initLetter.id = this.letterList[this.letterList.length - 1].id + 1;
      }
      initLetter.animationStartTime = window.performance.now();
      this.letterList.push({ ...initLetter, ...defailtConfig });
      await this.$nextTick();
      this.letterList[this.letterList.length - 1].element = this.$refs[
        `letter${initLetter.id}`
      ];
      this.totalNumber += 1;
    },
    clearCurrentClass() {
      if (
        this.letterList[this.currentIndex] &&
        this.letterList[this.currentIndex].element
      ) {
        this.letterList[this.currentIndex].element[0].children.forEach(
          (item) => {
            item.classList.remove("success_color");
            item.classList.remove("danger_color");
          }
        );
      }
      this.answer = "";
    },
    setMaxNumber() {
      if (this.type <= 5) {
        this.active = 0;
        this.max_num = 10;
      } else if (this.type <= 10) {
        this.max_num = 20;
        this.active = 1;
      } else if (this.type <= 15) {
        this.max_num = 30;
        this.active = 2;
      } else {
        this.max_num = 40;
        this.active = 3;
      }
      if (this.type % 5 == 0) {
        this.speed = 0.15;
      }
    },
  },
  created() {
    this.type = this.$route.query.type;
    this.setMaxNumber();
    this.defaultWord = keyGroup[this.$route.query.type];
    this.initLetter();
  },
  async mounted() {
    await this.$nextTick();
    const that = this;
    document.onkeydown = function(e) {
      let key = window.event.keyCode;
      if (key == 32 && that.isFail == false) {
        if (that.isPause == false) {
          that.stop();
        } else {
          that.continu();
        }
      }
      if (key == 13 && that.isPause == false) {
        that.clearCurrentClass();
      }
      if (key >= 65 && key <= 90) {
        that.handleKeyPress(String.fromCharCode(key).toUpperCase());
      }
    };
    this.start();
    this.rectTop = this.$refs.rocket_group.getBoundingClientRect().top;
  },
};
</script>
<style lang="scss" scoped>
.danger_color {
  color: #f56c6c;
}
.success_color {
  color: #67c23a;
}
.pointer {
  cursor: pointer;
}

.typing-game-conatiner {
  background: url("~@/assets/img/typing_game/typing_game_center_bc.png");
  background-position: center bottom;
  background-repeat: no-repeat;
  position: relative;
  left: 0;
  right: 0;
  .pause_left {
    width: 116px;
    height: 72px;
    cursor: pointer;
    position: fixed;
    z-index: 10;
    left: 0;
    top: 0;
  }
  .mosk {
    position: fixed;
    left: 0;
    top: 0;
    width: 100%;
    height: 100vh;
    background: rgba(0, 0, 0, 0.48);
    z-index: 99;

    .box {
      width: 431px;
      height: 370px;
      margin: 252px auto 0;

      .title {
        width: 431px;
        height: 178px;
      }

      .content {
        margin: 0 10px;
        padding-top: 10px;
        display: flex;
        justify-content: space-between;

        .first {
          width: 110px;
          height: 110px;
        }

        .secend {
          width: 110px;
          height: 110px;
        }
      }
    }
    .fail_box {
      margin: 0 auto;
      width: 646px;
      height: 664px;
      .content {
        display: flex;
        align-items: center;
        justify-content: center;
        padding-top: 460px;
        .icon {
          display: inline-block;
          width: 60px;
          height: 60px;
          background: url("~@/assets/img/typing_game/icon.png");
          background-size: 100% 100%;
          margin-right: 10px;
        }
        .title {
          font-size: 16px;
          font-weight: bold;
          color: #b55432;
          line-height: 34px;
        }
        .progress {
          border: 1px solid #eca927;
          border-radius: 30px;
          width: 160px;
        }
      }
      .footer {
        display: flex;
        justify-content: center;
        padding-top: 55px;
        .btn_group {
          display: flex;
          justify-content: center;
          width: 420px;
          img {
            width: 138px;
            height: 88px;
          }
        }
      }
    }
  }

  .game_content {
    margin: 0 auto;
    width: 1283px;
    height: 100vh;
    position: relative;
    top: 0;
    left: 0;

    .block {
      position: absolute;
      box-sizing: border-box;
      min-width: 75px;
      height: 75px;
      text-align: center;
      line-height: 75px;
      font-size: 53px;
      font-family: Source Han Sans CN;
      font-weight: bold;
      color: #5370f5;
      display: inline-block;
      background: #ffffff;
      border-radius: 9px;
      padding: 0 14px;
    }

    .active {
      color: #ffffffff;
      background-color: #60e2eaff;
    }

    .rocket_group {
      width: 100%;
      position: absolute;
      bottom: 28px;
      display: flex;
      justify-content: space-around;
      align-items: flex-end;

      .rocket_s {
        width: 39px;
        height: 55px;
      }

      .rocket_b {
        width: 150px;
        height: 202px;
      }
    }
  }
}
</style>
